package com.xjve.framework.hibernate.query.core;

import com.xjve.framework.hibernate.query.exception.SqlQueryException;
import com.xjve.framework.hibernate.query.model.SqlTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * SQL文件解析器，负责读取和解析SQL文件
 */
public class SqlFileParser {

    private static final Logger logger = LoggerFactory.getLogger(SqlFileParser.class);

    // SQL片段分割符
    private static final String SQL_SEPARATOR = "--sql";

    // 修改这行代码
    private static final Pattern NAME_PATTERN = Pattern.compile("--name:\\s*([\\w-]+)");

    // SQL备注标记
    private static final Pattern REMARK_PATTERN = Pattern.compile("--remark:\\s*([\\w-]+)");

    private final String sqlLocation;

    public SqlFileParser(String sqlLocation) {
        this.sqlLocation = sqlLocation;
    }

    /**
     * 解析所有SQL文件
     * @return SQL模板映射
     */
    public Map<String, SqlTemplate> parseAllSqlFiles() {
        Map<String, SqlTemplate> sqlTemplates = new HashMap<>();

        try {
            ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            Resource[] resources = resolver.getResources(sqlLocation + "/**/*.sql");

            for (Resource resource : resources) {
                parseSqlFile(resource, sqlTemplates);
            }

            logger.info("Successfully loaded {} SQL templates", sqlTemplates.size());
            return sqlTemplates;

        } catch (IOException e) {
            throw new SqlQueryException("Failed to load SQL files from location: " + sqlLocation, e);
        }
    }

    /**
     * 解析单个SQL文件
     * @param resource SQL资源文件
     * @param sqlTemplates SQL模板映射
     */
    private void parseSqlFile(Resource resource, Map<String, SqlTemplate> sqlTemplates) {
        try {
            String content = FileCopyUtils.copyToString(
                    new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8));

            String[] sqlFragments = content.split(SQL_SEPARATOR);

            for (String fragment : sqlFragments) {
                fragment = fragment.trim();
                if (StringUtils.hasText(fragment)) {
                    parseSqlFragment(fragment, sqlTemplates, resource.getFilename());
                }
            }

        } catch (IOException e) {
            throw new SqlQueryException("Failed to parse SQL file: " + resource.getFilename(), e);
        }
    }

    /**
     * 解析SQL片段
     * @param fragment SQL片段内容
     * @param sqlTemplates SQL模板映射
     * @param fileName 文件名
     */
    private void parseSqlFragment(String fragment, Map<String, SqlTemplate> sqlTemplates, String fileName) {
        try {
            String[] lines = fragment.split("\n");

            String name = null;
            String remark = null;
            StringBuilder sqlBuilder = new StringBuilder();

            for (String line : lines) {
                String trimmedLine = line.trim();

                // 提取名称
                if (trimmedLine.startsWith("--name:")) {
                    Matcher matcher = NAME_PATTERN.matcher(trimmedLine);
                    if (matcher.find()) {
                        name = matcher.group(1);
                    }
                }
                // 提取备注
                else if (trimmedLine.startsWith("--remark:")) {
                    Matcher matcher = REMARK_PATTERN.matcher(trimmedLine);
                    if (matcher.find()) {
                        remark = matcher.group(1);
                    }
                }
                // 跳过空行和注释
                else if (StringUtils.hasText(trimmedLine) && !trimmedLine.startsWith("--")) {
                    sqlBuilder.append(line).append("\n");
                }
            }

            if (StringUtils.hasText(name)) {
                String sql = sqlBuilder.toString().trim();
                if (StringUtils.hasText(sql)) {
                    SqlTemplate template = new SqlTemplate(name, sql, remark, fileName);
                    sqlTemplates.put(name, template);
                    logger.debug("Loaded SQL template: {} - {}", name, remark);
                } else {
                    logger.warn("SQL template {} has empty SQL content in file {}", name, fileName);
                }
            } else {
                logger.warn("Found SQL fragment without name in file {}", fileName);
            }

        } catch (Exception e) {
            throw new SqlQueryException("Failed to parse SQL fragment in file " + fileName, e);
        }
    }
}
